<?php
/*********************************************
 *  CPG Dragonfly™ CMS
 *********************************************
	Copyright © since 2010 by CPG-Nuke Dev Team
	http://dragonflycms.org

	Dragonfly is released under the terms and conditions
	of the GNU GPL version 2 or any later version

	$Source$
	$Revision$
	$Author$
	$Date$
**********************************************/

class Poodle_HTTP_Request_Socket extends Poodle_HTTP_Request
{
	public function supportsSSL()
	{
		return function_exists('openssl_open');
	}

	public function get($request_url, $extra_headers = null)
	{
		return $this->doRequest($request_url, $extra_headers);
	}

	public function post($request_url, $body, $extra_headers = null)
	{
		return $this->doRequest($request_url, $extra_headers, $body);
	}

	protected function doRequest($request_url, $extra_headers = null, $body = null)
	{
		$method = is_null($body) ? 'GET' : 'POST';
		$url    = $request_url;
		$etime  = time() + $this->timeout;
		$redir  = true;
		if (is_array($body)) { $body = http_build_query($body); }
		do
		{
			if (!$this->canFetchURI($url)) {
				return null;
			}

			if (!$this->allowedURI($url)) {
				trigger_error("Fetching URL not allowed: $url");
				return null;
			}

			$parts = parse_url($url);

			// Set a default port.
			$port = 0;
			if (array_key_exists('port', $parts)) {
				$port = $parts['port'];
			} else if ('http' == $parts['scheme'] || 'https' != $parts['scheme']) {
				$parts['port'] = self::getSchemePort($parts['scheme']);
			} else {
				return null;
			}

			if (!array_key_exists('path', $parts)) {
				$parts['path'] = '/';
			}

			$headers = array(
				"{$method} {$parts['path']}".(isset($parts['query']) ? "?{$parts['query']}" : '')." HTTP/1.0",
				"Host: ".$parts['host'].($port ? ":".$port : ''),
				"User-Agent: {$this->user_agent}",
			);
			if ($extra_headers && is_array($extra_headers)) {
				$headers = array_merge($headers, $extra_headers);
			}
			if (!is_null($body)) {
				$headers[] = "Content-type: application/x-www-form-urlencoded";
				$headers[] = "Content-length: ".strlen($body);
			}

			if ('https' == $parts['scheme']) { $parts['host'] = 'ssl://'.$parts['host']; }

			$errno = 0;
			$errstr = '';

			$sock = fsockopen($parts['host'], $parts['port'], $errno, $errstr, $this->timeout);
			if (false === $sock) {
				return false;
			}

			stream_set_timeout($sock, $this->timeout);

			fwrite($sock, implode("\r\n", $headers) . "\r\n\r\n");
			if (!is_null($body)) {
				fwrite($sock, $body);
			}

			$data = '';
			$kilobytes = 0;
			while (!feof($sock) && $kilobytes < $this->max_response_kb) {
				$data .= fread($sock, 1024);
				++$kilobytes;
			}

			fclose($sock);

			// Split response into header and body sections
			list($headers, $body) = explode("\r\n\r\n", $data, 2);
			$headers = explode("\r\n", $headers);

			$code = explode(' ', $headers[0]);
			$code = intval($code[1]);

			// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3
			// In response to a request other than GET or HEAD, the user agent MUST NOT
			// automatically redirect the request unless it can be confirmed by the user
			if (is_null($body) && in_array($code, array(301, 302, 307))) {
				$url = self::findRedirect($headers, $url);
			} else {
				$redir = false;
				return new $this->result_class($request_url, $url, $code, self::parseHeaders($headers), $body);
			}

		} while ($redir && ($etime-time() > 0));

		return null;
	}

}
